#include "volumeactivation.h"

#include <mosquitto.h>
#include <QDateTime>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define PROGRAM_NAME "kylin-activation-volume"
#define LOG_NAME "/.log/kylin-activation/kylin-activation-volume.log"

static FILE *fp_log = NULL;
QString toDir;

void msgHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
    static char logPath[255] = {0};
    static int uid = -1;
    static int pid = 0;

    Q_UNUSED(context);

    QDateTime currentTime = QDateTime::currentDateTime();
    QString timeStr = currentTime.toString("yy.MM.dd hh:mm:ss +zzz");
    pid = (int)getpid();
    // 获取用于控制命令行输出的环境变量
    char *ctrlEnv = getenv("VOLUME_DEBUG");
    QString env;

    // 格式化输出字符串，添加消息发生时间、消息等级
    QString outMsg, outMsg_std;
    outMsg_std = QString("%1").arg(msg);
    switch (type) {
    case QtDebugMsg:
        outMsg = QString("[%1 D .%2]: %3").arg(timeStr).arg(pid).arg(msg);
        break;
    case QtInfoMsg:
        outMsg = QString("[%1 D .%2]: %3").arg(timeStr).arg(pid).arg(msg);
        break;
    case QtWarningMsg:
        outMsg = QString("[%1 D .%2]: %3").arg(timeStr).arg(pid).arg(msg);
        break;
    case QtCriticalMsg:
        outMsg = QString("[%1 D .%2]: %3").arg(timeStr).arg(pid).arg(msg);
        break;
    case QtFatalMsg:
        outMsg = QString("[%1 D .%2]: %3").arg(timeStr).arg(pid).arg(msg);
    }

    if (fp_log != NULL) {
        // 日志文件存在，则输出到日志文件中
        fprintf(fp_log, "%s\n", outMsg.toUtf8().data());
        fflush(fp_log);
    }

    fprintf(stdout, "%s\n", outMsg_std.toStdString().c_str());

    // 遇到致命错误，需要终止程序（这里终止程序是可选的）
    if (type == QtFatalMsg)
        abort();
}

void log_env_init(){
    static int uid = -1;
    static char logPath[98] = {0};
    bool _is_root = false;
    toDir = QDir::homePath();
    toDir += "/.log/kylin-activation/";
    QDir dir(toDir);
    if(!dir.exists()) {
        dir.mkdir(toDir);
    }

    // 初始执行时，设置log文件路径
    if (uid == -1) {
        uid = getuid();
    }
    if (uid == 0) {
        // root user
        sprintf(logPath, "/var/log/kylin-activation/kylin-activation-ui.log");
        _is_root = true;
    } else {
        // normal user
        std::string str = QDir::homePath().toStdString();
        const char* ch = str.c_str();
        sprintf(logPath, "%s%s", ch, LOG_NAME);
    }

    if (access(logPath, F_OK|W_OK) == 0) { // log文件存在且可写
        if (fp_log == NULL)
            fp_log = fopen(logPath, "a+");
        QFileInfo info(logPath);
        if (info.size() > 1024*1024*20) { //20MB
            fclose(fp_log); fp_log = NULL;
            QFile fileclean(logPath);
            fileclean.open(QIODevice::WriteOnly | QIODevice::Text | QFile::Truncate);
            fileclean.close();
            if (fp_log == NULL)
                fp_log = fopen(logPath, "a+");
        }
    } else if (access(logPath, F_OK) != 0){ //文件不存在
        if (fp_log == NULL) {
            if (_is_root) { //root用户日志文件
                QDir* dir = new QDir();
                if(!dir->exists("/var/log/kylin-activation/")){
                    dir->mkpath("/var/log/kylin-activation/");
                }
                fp_log = fopen(logPath, "a+");
                if (fp_log == NULL)
                    printf("Can't open logfile!\n");
            } else {
                fp_log = fopen(logPath, "a+");
                if (fp_log == NULL)
                    printf("Can't open logfile!\n");
            }
        }
    } else {
        // log文件不可写，则需要判断是否被打开过，被打开过就需要关闭
        if (fp_log != NULL)
            fclose(fp_log);
        fp_log = NULL;
    }
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    log_env_init();
    qInstallMessageHandler(msgHandler);
    //通过/proc/cmdline判断是否处于livecd模式
    FILE *fp;
    char result_buf[2048];
    QString check;
    bool livecd_flag = false;

    qDebug()<<"sleep 30 to get activate status.";
    sleep(30);

    fp = popen("cat /proc/cmdline","r");
    if(fp == NULL) {
        printf("cant open /proc/cmdline !");
    } else {
        while(fgets(result_buf, sizeof(result_buf), fp) != NULL && livecd_flag == false) {
            check = QString(result_buf);
            livecd_flag = check.contains("casper");
        }
    }

    if(livecd_flag) { //处于livecd模式，不提供激活
        qApp->exit(0);
    }

    //创建MQTT连接对象
    VolumeActivation va;
    //通过序列号检查授权文件是否合法
    if(get_serial_number().isEmpty()) {
        qApp->exit(0);
    }
    va.searchServerIp();

//    va.timer->start(4000);

    int ret = a.exec();
    return ret;
}
